﻿/**
 * Copyright (C) 2011 original author and authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NGuice.Inject.Matcher;
using NGuice.Inject.Internal.Util;
using AopAlliance.Intercept;
using System.Reflection;

namespace NGuice.Inject.Spi
{
    // 完成！
    /// <summary>
    /// 注册匹配类中匹配方法的拦截器。实例在模型中使用
    /// <code>NGuice.Inject.Binder#BindInterceptor(Matcher, Matcher, MethodInterceptor[])</code>
    /// 显式的创建：
    /// <code>
    /// BindInterceptor(Matchers.subclassesOf(typeof(MyAction)), Matchers.AnnotatedWith(Transactional.class),new MyTransactionInterceptor());
    /// </code>
    /// 或者使用TypeEncounter#bindInterceptor(Matcher,org.aopalliance.intercept.MethodInterceptor[])中的可注入类型监听器中使用
    /// </summary>
    public sealed class InterceptorBinding : IElement
    {
        private readonly object source;

        private readonly IMatcher classMatcher;//泛型参数为Type的超类

        private readonly IMatcher methodMatcher;//泛型参数为MethodInfo的超类

        private readonly ImmutableList<IMethodInterceptor> interceptors;


        public InterceptorBinding(object source, IMatcher classMatcher, IMatcher methodMatcher, IMethodInterceptor[] interceptors)
        {
            this.source = Preconditions.CheckNotNull(source, "source");
            this.classMatcher = Preconditions.CheckNotNull(classMatcher, "classMatcher");
            //泛型参数为Type的超类
            Preconditions.CheckSuperGenericParameter<Type>(classMatcher);
            this.methodMatcher = Preconditions.CheckNotNull(methodMatcher, "methodMatcher");
            //泛型参数为MethodInfo的超类
            Preconditions.CheckSuperGenericParameter<MethodInfo>(classMatcher);
            this.interceptors = ImmutableList<IMethodInterceptor>.Of(interceptors);
        }

        public object Source
        {
            get { return source; }
        }

        public IMatcher ClassMatcher
        {
            get { return classMatcher; }
        }

        public IMatcher MethodMatcher
        {
            get { return methodMatcher; }
        }

        public ImmutableList<IMethodInterceptor> Interceptors
        {
            get { return interceptors; }
        } 

        public T AcceptVisitor<T>(IElementVisitor<T> visitor)
        {
            return visitor.Visit(this);
        }

        public void ApplyTo(IBinder binder)
        {
            binder.WithSource(Source).BindInterceptor(classMatcher, methodMatcher, interceptors.ToArray());
        }
    }
}
